In This Part
by K. David White
In This Chapter
In most books on MFC and Visual C++, the document/view architecture is usually given top billing. There are reasons for this. Microsoft, in developing MFC, decided that a consistent framework was needed to encapsulate the Windows functionality. Although some might argue that the document/view architecture is really all you need to understand in order to create robust MFC applications, it is apparent to the experienced MFC developer that this is not the case. The document/view architecture is a consistent framework and provides the necessary control over MFC applications; however, it lends itself to expansion and flexibility. There are also many situations in which the doc/view architecture should be abandoned entirely. This chapter tries to unlock the doc/view framework and concentrate on using it to the best advantage.
The first section covers all the components and provides an overview of the doc/view architecture. The Creating New Documents section explores the means necessary to utilize the framework to create new documents. Next, the chapter explores views and how the views interact with the document and frames. After you gain an understanding of views, youll take a look at the base of this framework, the document. With this knowledge of all the pieces, youll look to ways to manage it above and beyond the framework. The last section of this chapter takes a quick look at other frameworks to consider.
Most senior-level developers understand how data should be managed and how it should be presented. In object-oriented presentation, a class contains member variables that are accessed through member functions. This encapsulation ensures that the class is basically responsible for itself. How then does an application that contains many classes manage the data contained within those classes in a controlled and structured manner? If you look at the problem of presenting data versus managing data, you can quickly see where the document/view architecture solves this dilemma. Lets take a closer look.
As you can easily see from Figure 7.1, the document contains the data store, and the view is a window into a certain location of that data. This store can be ultimately a database connection, a disk storage file, or some other mechanism. Later sections look at the problem of where to store data needed by a view. Simply put, however, the view is a window into the data that is stored within the document. Within this architecture, the document is responsible for exposing the necessary interfaces for the view to display the data.
Figure 7.1 A simple representation of the document/view architecture.
The doc/view architecture comes in two primary flavors: the Single Document Interface (SDI) and the Multiple Document Interface (MDI). An SDI application contains one and only one document class with which to control the data. The MDI application can contain any number of documents. You will notice from Figure 7.2 that the documents are created through a document template class.
Figure 7.2 Document types within the doc/view architecture.
The solid dark lines in Figure 7.2 represent the instantiation path for creating views, and the dotted lines represent the pointer direction. Now that youve seen how this picture is painted, lets start looking at each individual piece of the puzzle.
Note:There are many different document classes, which are usually derived from the base class CDocument. For instance, if you are using COM and want compound document support, you might want to choose the COleDocument class.
Note:As Chapter 27, MAPI and MFC, points out, the CDocument class also provides the necessary structure to support the Microsoft Messaging Application Program Interface (MAPI). This is done through the two CDocument member functions: OnFileSendMail and OnUpdateFileSendMail
Imagine, if you will, trying to manage all the necessary information about data without the different classes to define the structure of the data. But what about relating the data contained within the document with the necessary display constraints defined by a view? Some overhead mechanism is needed to keep track of the document and its relation to the views that it owns. Enter the document template.
The document template class defines all the menus, accelerators, and other important resources that a view requires. This template mechanism loosely ties the document class with the view class.
As Figure 7.2 shows, the CWinApp class creates and contains a pointer to one or more document templates, depending on whether the application is an SDI or MDI application. CSingleDocTemplate is responsible for managing one and only one CDocument class. CMultiDocTemplate maintains a list of CDocument classes that are currently opened from that template. MFC breaks the object-oriented paradigm (only a little bit) here by allowing the CDocument class and the CDocTemplate classes to be friends. The CDocument contains a back pointer to its owning CDocTemplate class. This allows an application to traverse the CWinApp/CDocument/CView hierarchy in either direction.
Whenever the CWinApp class creates a document template, it does so in a two-step process. It first instantiates the DocTemplate class and then performs an AddDocument to add the document to the templates list and sets the back pointer. Listing 7.1 shows the CSingleDocTemplate constructor, and Listing 7.2 shows the AddDocument method.
Notice that the back pointer is set during the AddDocument method. One reason that it is done this way is to enable the user to create templates and specify document types outside what the framework automatically provides. Listing 7.3 is from the SDI sample UNL_Single.
Listing 7.1 The CSingleDocTemplate Constructor
CSingleDocTemplate::CSingleDocTemplate(UINT nIDResource,
CRuntimeClass* pDocClass, CRuntimeClass* pFrameClass,
CRuntimeClass* pViewClass)
: CDocTemplate(nIDResource, pDocClass, pFrameClass, pViewClass)
{
m_pOnlyDoc = NULL;
}
Listing 7.2 The CSingleDocTemplate AddDocument Method
void CSingleDocTemplate::AddDocument(CDocument* pDoc)
{
ASSERT(m_pOnlyDoc == NULL); // one at a time, please
ASSERT_VALID(pDoc);
CDocTemplate::AddDocument(pDoc);
m_pOnlyDoc = pDoc;
}
Listing 7.3 The UNL_Single.cpp InitInstance Routine
CSingleDocTemplate* pDocTemplate;
pDocTemplate = new CSingleDocTemplate(
IDR_MAINFRAME,
RUNTIME_CLASS(CUNL_SingleDoc),
RUNTIME_CLASS(CMainFrame), // main SDI frame window
RUNTIME_CLASS(CUNL_SingleView));
AddDocTemplate(pDocTemplate);